package br.caixa2.entities;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import br.caixa2.enums.PasswordDomain;
import br.caixa2.enums.TypeOperation;
import br.caixa2.exceptions.InsufficientBalanceException;
import br.caixa2.interfaces.Account;

import com.br.generateswingview.annotations.Alias;
import com.br.generateswingview.annotations.Ignore;

public abstract class AccountImpl implements Account {
	@Alias( "Cliente" )
	private final Client client;
	@Alias( "Número da conta" )
	private int number;
	@Ignore
	@Alias( "Saldo" )
	private double balance;
	@Ignore
	private final List<Extract> extract;
	@Ignore
	private String password;

	protected void teste() {}

	AccountImpl( Client client, int number ) {
		extract = new ArrayList<Extract>();
		this.number = number;
		this.client = client;
		Random radom = new Random();
		int index = radom.nextInt( PasswordDomain.values().length );
		password = PasswordDomain.values()[index].toString();
		index = radom.nextInt( PasswordDomain.values().length );
		password += "-" + PasswordDomain.values()[index].toString();
		index = radom.nextInt( PasswordDomain.values().length );
		password += "-" + PasswordDomain.values()[index].toString();
	}

	@Override
	public void draw( double value ) {
		if ( value > 0 ) {
			if ( valitacaoDeSaque( value ) ) {
				balance -= value;
				addExtract( new Date(), "Saque na conta", TypeOperation.DRAW, value );
			} else
				throw new InsufficientBalanceException();
		} else
			throw new IllegalArgumentException( "Valor de saque inválido" );
	}

	public abstract boolean valitacaoDeSaque( double value );

	@Override
	public void deposit( double value ) {
		if ( value > 0 ) {
			balance += value;
			addExtract( new Date(), "Deposito na conta", TypeOperation.DEPOSIT, value );
		} else
			throw new IllegalArgumentException( "Valor de saque inválido" );
	}

	@Override
	public void transfer( Account destiny, double value ) {
		draw( value );
		destiny.deposit( value );
		extract.remove( extract.size() - 1 );
		addExtract( new Date(), "Transferencia para conta de nº " + ( (AccountImpl) destiny ).getNumber(), TypeOperation.TRANSFER, value );
	}

	public void addExtract( Date date, String description, TypeOperation type, double value ) {
		Extract e = new Extract( date, description, type, value );
		extract.add( e );
	}

	public Client getClient() {
		return client;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber( int number ) {
		this.number = number;
	}

	public double getBalance() {
		return balance;
	}

	public List<Extract> getExtract() {
		return extract;
	}

	public void setBalance( double balance ) {
		this.balance = balance;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword( String password ) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "AccountImpl [client=" + client + ", number=" + number + ", balance=" + balance + ", extract=" + extract + "]";
	}
}